﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

using LowLevelGraphics.Drawing;

namespace LowLevelGraphics.Extractors
{
    /// <summary>
    /// This is used if you got parts of a pic (pic is broken into several pieces),
    /// so this tries to refit them to a whole pic again.
    /// e.g. you cut a pic into several pieces. Each piece has got another rotation
    /// Each part will be deskewed and then matched to the other pieces.
    /// </summary>
    
    public delegate Rectangle BoundingBoxEstimatorDelegate(object _oObject);

    /// <summary>
    /// Bounding Box estimator
    /// </summary>
    public class BoundingBoxEstimator
    {
        protected Rectangle m_Rectangle = Rectangle.Empty;
        protected BoundingBoxEstimatorDelegate m_Delegate = null;
        protected IEnumerable<Point> m_aPointList = null;

        public BoundingBoxEstimator()
        {
            //m_Delegate = set default delegate here...
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="AutoReFit"/> class.
        /// </summary>
        public BoundingBoxEstimator(BoundingBoxEstimatorDelegate _delegate)
        {
            m_Delegate = _delegate;
        }

        /// <summary>
        /// Get rectangle from Points
        /// </summary>
        /// <param name="_aPoint"></param>
        /// <returns></returns>
        public BoundingBoxEstimator(IEnumerable<Point> _aPoint)
        {
            m_aPointList = _aPoint;
            m_Delegate = new BoundingBoxEstimatorDelegate(EstimateByPointList);            
        }

        /// <summary>
        /// Estimate Bounding Box
        /// </summary>
        /// <param name="_unsafeBitmap"></param>
        public Rectangle Estimate(UnsafeBitmap _unsafeBitmap)
        {
            m_Rectangle = m_Delegate.Invoke(m_aPointList);
            return m_Rectangle;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="_aObject"></param>
        /// <returns></returns>
        private Rectangle EstimateByPointList(object _aObject)
        {
            Rectangle rectangle = Rectangle.Empty;
            IEnumerable<Point> aPoint = (IEnumerable<Point>)_aObject;
            List<Point> aPointList = new List<Point>();
            aPointList.AddRange(aPoint);
            aPointList.Sort(new PointSort(PointSort.Mode.X));

            if (aPointList.Count == 0)
            {
                return rectangle;
            }

            int nMinX = aPointList[0].X;
            int nMaxX = aPointList[aPointList.Count - 1].X;  

            aPointList.Sort(new PointSort(PointSort.Mode.Y));
            int nMinY = aPointList[0].Y;
            int nMaxY = aPointList[aPointList.Count - 1].Y;
            rectangle = Rectangle.FromLTRB(nMinX, nMinY, nMaxX, nMaxY);
            return rectangle;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="_bitmap"></param>
        public void Draw(Pen pen, UnsafeBitmap _bitmap)
        {
            UnsafeGraphics graphics = UnsafeGraphics.FromImage(_bitmap);
            graphics.DrawRectangle(pen, m_Rectangle);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="_bitmap"></param>
        public void Draw(Pen pen, Bitmap _bitmap)
        {
            Graphics graphics = Graphics.FromImage(_bitmap);
            graphics.DrawRectangle(pen, m_Rectangle);
        }


        /// <summary>
        /// Get bounding box rectangle
        /// </summary>
        public Rectangle Rectangle
        {
            get { return m_Rectangle; }
        }
    }
}
